﻿
#ifndef QSS_H
#define QSS_H

#include <QWidget>
#include <QMainWindow>
#include <QDialog>
#include <QMessageBox>
#include <QFrame>
#include <QDockWidget>
#include <QPushButton>
#include <QAbstractNativeEventFilter>
#include <QDebug>
#include <QThread>

#include "ui_qsstoast.h"
#include "ui_process.h"
#include <QScreen>

#ifdef __MINGW32__
#include "windows.h"
#include "winuser.h"
#pragma comment(lib, "libuser32.a")
#endif

class QPushButton;
class QLabel;
class QMouseEvent;

#define STANDARD_DPI 96.0

#ifndef WM_DPICHANGED
#define WM_DPICHANGED 0x02e0
#endif



class QssPushButton : public QPushButton{
public:
    QssPushButton(QWidget *parent,QString objName);

};
// 获取当前dpi
uint16_t CurrentDPI(QWidget* widget,int monitor);

class  QssTtitleBar : public QWidget
{
    Q_OBJECT

signals:
    void OnMaxOrRestore(bool );
public:
    enum QTitleBar_Button
    {
        QTitleBar_Button_Min = 		0x00000001,
        QTitleBar_Button_Max = 		0x00000002,
        QTitleBar_Button_Restore = 	0x00000004,
        QTitleBar_Button_Close = 	0x00000008
    };

    enum QTitleBar_Type
    {
        QTitleBar_Type_MainWindow = QTitleBar_Button_Min |
        QTitleBar_Button_Max |QTitleBar_Button_Restore | QTitleBar_Button_Close,
        QTitleBar_Type_Dialog = QTitleBar_Button_Close,
        QTitleBar_Type_MessageBox = QTitleBar_Button_Close
    };

    QssTtitleBar(QWidget *parent, QTitleBar_Type type = QTitleBar_Type_MainWindow);
    ~QssTtitleBar();

    void setTitle(QString title);
    void setIcon( QIcon icon);

    void setMaxOrRestore(bool val);
    bool maxOrRestore(){return m_maxOrRestore;}
    void SetMainWindow(QMainWindow*);
    QRect& normalRect(){return m_rcNormal;}

private slots:
    void onMaxOrRestore();

protected:
    void paintEvent(QPaintEvent *);
    void mouseMoveEvent(QMouseEvent * ev);
    void mousePressEvent(QMouseEvent * ev);
    void mouseReleaseEvent(QMouseEvent * ev);
    bool eventFilter(QObject * obj, QEvent * ev);

private:
    QPushButton* m_closeBtn;
    QPushButton* m_maxBtn;
    QPushButton* m_restoreBtn;
    QPushButton* m_minBtn;

    QLabel* m_titlebarTitle;
    QMainWindow *m_Main;
    bool m_maxOrRestore;
    bool m_pressed;

    QPoint m_pressedPos;

    QRect m_rcValid;//桌面最大可用尺寸
    QRect m_rcNormal;//还原后窗口尺寸

    QTitleBar_Type m_type;
};
class QssEventFilter
    : public QAbstractNativeEventFilter
{
public:
    virtual bool nativeEventFilter(const QByteArray &eventType, void *message, long *) Q_DECL_OVERRIDE
    {
        return false;
    }
};

class  QssMainWindow : public QMainWindow
{
    Q_OBJECT

public slots:
    void OnMaxOrRestore(bool max);
    void PhisycalDpiChange(qreal);
    void LogicalDpiChange(qreal);

public:
    typedef enum{
        EVENT_MOVE = 523,
    } EVENT_CUSTOM;
    QssMainWindow(QWidget *parent = 0, Qt::WindowFlags flags = 0,float scale = 1);
    virtual ~QssMainWindow();
    void AdapteDpi();
    QWidget *TitleBar();
    void RangeObject();
    void DetectDpiChange();
    void ShowMask();
    void HideMask();
    void show();
    void showMinimized();
    void showMaximized();
    void showFullScreen();
    void showNormal();
    void setCursorShape(int CalPos)	;
    void setWindowTitle( QString title );
    void setWindowIcon( QIcon icon );
    int CalCursorPos(QPoint pt, int colPos);
    void SetTitleHeight(uint32_t height);
    inline QssTtitleBar* titleBar(){return m_titleBar;}
    inline QFrame* frame(){return m_frame;}
        int CalCursorCol(QPoint pt);    //计算鼠标X的位置
    virtual bool eventFilter(QObject * obj, QEvent * ev);

private:
    void onMouseMoveEvent(QMouseEvent * ev);
    void onMousePressEvent(QMouseEvent * ev);
    void onMouseReleaseEvent(QMouseEvent * ev);
    void dpiScaleChildren();
    void detectDpi();

    void rangeObjectList(QObject*obj,int indent);
protected:
    QFrame* m_frame;
    QRect mFrameRect;
    QRect m_CentralRect;
    QssTtitleBar* m_titleBar;
    void showEvent(QShowEvent *ev);

    virtual void ScaleChanged(float scale) ;
    virtual WId GetWID() const;
    virtual void SetScale(float scale) ;
    virtual void paintEvent(QPaintEvent *event);

private:
    QRect m_rcValid;//桌面最大可用尺寸
    QRect m_rcNormal;//还原后窗口尺寸
    QRect m_rcNormalCentral;//还原后central widget的尺寸
    /**  边框调整大小相关 */
    QPoint m_pos;
    bool m_mousePressedInBoundy;
    bool m_left,m_right,m_top,m_bottom;

    int     m_iCalCursorPos;
    bool    m_bLeftPress;
    QRect   m_rtPreGeometry;
    QPoint  m_ptViewMousePos;
    float   m_dpi_ratio;
    QWidget *mShadowMask;
    QScreen *mCurrentScreen;

};

class  QssDialog : public QDialog
{
    Q_OBJECT

public:
    QssDialog(QWidget *parent);
    virtual ~QssDialog();

    void ShowMask();
    void HideMask();

    void show();
    void raise();
    void activateWindow();

    int exec();

    void setWindowTitle( QString title );
    void setWindowIcon( QIcon icon );

    inline QssTtitleBar* titleBar(){return m_titleBar;}
    inline QFrame* frame(){return m_frame;}

    virtual bool eventFilter(QObject * obj, QEvent * ev);

private:
    void onMouseMoveEvent(QMouseEvent * ev);
    void onMousePressEvent(QMouseEvent * ev);
    void onMouseReleaseEvent(QMouseEvent * ev);

private:
    QWidget* m_parent;

    QFrame* m_frame;
    QssTtitleBar* m_titleBar;

    QRect m_rcValid;

    /**  边框调整大小相关 */
    QRect mFrameRect;
    QPoint m_pos;
    bool m_mousePressedInBorder;
    bool m_left,m_right,m_top,m_bottom;
    QWidget *mShadowMask;

};


// 可停靠widget
class  QssDockWidget : public QDockWidget
{
    Q_OBJECT

public:
    QssDockWidget(QWidget *parent);

    void ShowMask();
    void HideMask();
    virtual ~QssDockWidget();

    void show();
    void raise();
    void activateWindow();

    int exec();

    void setWindowTitle( QString title );
    void setWindowIcon( QIcon icon );
    void paintEvent(QPaintEvent *);
    inline QssTtitleBar* titleBar(){return m_titleBar;}
    inline QFrame* frame(){return m_frame;}

    virtual bool eventFilter(QObject * obj, QEvent * ev);

private:
    void onMouseMoveEvent(QMouseEvent * ev);
    void onMousePressEvent(QMouseEvent * ev);
    void onMouseReleaseEvent(QMouseEvent * ev);

private:
    QFrame* m_frame;
    QssTtitleBar* m_titleBar;

    QRect m_rcValid;
    QWidget* m_parent;

    /**  边框调整大小相关 */
    QRect mFrameRect;
    QPoint m_pos;
    bool m_mousePressedInBorder;
    bool m_left,m_right,m_top,m_bottom;
    QWidget *mShadowMask;

};

class  QssMessageBox : public QMessageBox
{
    Q_OBJECT

public:
    explicit QssMessageBox(QWidget *parent = 0);
    QssMessageBox(Icon icon, const QString &title, const QString &text,
        StandardButtons buttons = NoButton, QWidget *parent = 0,
        Qt::WindowFlags flags = Qt::Widget | Qt::FramelessWindowHint);
    ~QssMessageBox();

    inline QssTtitleBar* titleBar(){return m_titleBar;}
    inline QFrame* frame(){return m_frame;}

    static QMessageBox::StandardButton tips(const QString & text, QWidget* parent = 0,
        const QString & title = QString::fromLocal8Bit("提示"), StandardButtons btn = QMessageBox::Ok);
    static QMessageBox::StandardButton warn(const QString & text, QWidget* parent = 0,
        const QString & title = QString::fromLocal8Bit("警告"), StandardButtons btn = QMessageBox::Ok);
    static QMessageBox::StandardButton error(const QString & text, QWidget* parent = 0,
        const QString & title = QString::fromLocal8Bit("错误"), StandardButtons btn = QMessageBox::Ok);
    static QMessageBox::StandardButton ask(const QString & text, QWidget* parent = 0,
        const QString & title = QString::fromLocal8Bit("询问"), StandardButtons btn = QMessageBox::Yes | QMessageBox::No);

    /** 覆盖定义，适配原有QMessageBox */
    static StandardButton information(QWidget *parent, const QString &title,
        const QString &text, StandardButtons buttons = Ok,
        StandardButton defaultButton = NoButton);
    static StandardButton question(QWidget *parent, const QString &title,
        const QString &text, StandardButtons buttons = QMessageBox::Ok,
        StandardButton defaultButton = QMessageBox::NoButton);
    static StandardButton warning(QWidget *parent, const QString &title,
        const QString &text, StandardButtons buttons = QMessageBox::Ok,
        StandardButton defaultButton = QMessageBox::NoButton);
    static StandardButton critical(QWidget *parent, const QString &title,
        const QString &text, StandardButtons buttons = QMessageBox::Ok,
        StandardButton defaultButton = QMessageBox::NoButton);

    static QMessageBox::StandardButton regard(const QString & text, QWidget* parent = 0,
        const QString & title = QString::fromLocal8Bit("关于"));
    static QMessageBox::StandardButton regard(const QString & text, QIcon icon, QWidget* parent = 0,
        const QString & title = QString::fromLocal8Bit("关于"));

    static QMessageBox::StandardButton regardQt(QWidget* parent = 0,
        const QString & title = QString::fromLocal8Bit("关于Qt"));

    static void about(QWidget *parent, const QString &title, const QString &text);
    static void about(QWidget *parent, const QString &title, const QString &text, QIcon icon);

    static void aboutQt(QWidget *parent, const QString &title = QString());

    bool eventFilter(QObject * obj, QEvent * ev);

private:
    QFrame* m_frame;
    QssTtitleBar* m_titleBar;
    QWidget* m_parent;

    QRect m_rcValid;
};



class QssMaskWidget : public QWidget
{
    Q_OBJECT

public:
    QssMaskWidget(QWidget *parent = Q_NULLPTR);
    virtual ~QssMaskWidget();
    virtual bool eventFilter(QObject * obj, QEvent * ev);

public:

protected:
    virtual void paintEvent(QPaintEvent *event);

private:
    QWidget *mParent;
    Ui::Toast ui;
};

class QssToastWidget : public QWidget
{
    Q_OBJECT

public:
    QssToastWidget(QWidget *parent = Q_NULLPTR);
    ~QssToastWidget();

    void setText(const QString& text);

    void showAnimation(int timeout = 2000);// 动画方式show出，默认2秒后消失

public:
    // 静态调用
    static void showTip(const QString& text, QWidget* parent = nullptr);

protected:
    virtual void paintEvent(QPaintEvent *event);

private:
    Ui::Toast ui;
};



class QSSProcessBar : public QDialog
{
    Q_OBJECT

public:
    explicit QSSProcessBar(QWidget *parent = nullptr);
    ~QSSProcessBar();
    void showEvent(QShowEvent *) override;

public slots:
    void on_percent(int);
    void on_done_close();
private:
    Ui::Process *ui;
    QWidget *mParent;
};

// 异步执行任务，不会阻塞ui线程
class   QSSASyncProcess : public QObject{
    Q_OBJECT

public:
    QSSASyncProcess(QWidget *parent = nullptr);
    ~QSSASyncProcess();
    int Start(void*);
    QThread &Thread();
signals:
    void DonePercent(int);
    void Done();
    void StartRun(void *);
public slots:
    virtual void Run(void *) ;
protected:
    QWidget *mParent;
    QThread mThread;
};

#define tipBox(text)   	QssMessageBox::tips(text)
#define warnBox(text)  	QssMessageBox::warn(text)
#define errBox(text)	QssMessageBox::error(text)
#define askBox(text)   	QssMessageBox::ask(text)

#define aboutBox(title, text)	QssMessageBox::regard(text, 0,title)
#define aboutQtBox()			QssMessageBox::regardQt()

#endif // QSS_H
